<template>
  <div>
    <a-row :gutter="24">
      <a-col :xl="8" :lg="8" :md="8" :sm="24" :style="{marginBottom: '10px'}">
        <a-card title="告警按严重性级别分布" :bordered="false" :headStyle="{padding: '0 15px', border:0}" style="width:100%">
          <rose-type-chart id="roseType" :opiton="optionRoseType" style="width:100%; height:220px"></rose-type-chart>
        </a-card>
      </a-col>

      <a-col :xl="16" :lg="16" :md="16" :sm="24" :style="{marginBottom: '10px'}">
        <a-card :loading="loading" :bordered="false" :headStyle="{padding: '0', border:0}" :body-style="{padding: '0'}" class="cardpadding">
          <div class="salesCard">
            <a-tabs default-active-key="1" size="large" :tab-bar-style="{marginBottom: '24px', paddingLeft: '16px'}">
              <!-- 根据业务应用分布 -->
              <a-tab-pane loading="true" tab="业务应用" key="1">
                <div class="chartbox">
                  <ve-histogram :data="countAppName" :judge-width="true" :extend="chartExtend" height="220px"></ve-histogram>
                </div>
              </a-tab-pane>
              <!-- 根据数据中心分布 -->
              <a-tab-pane loading="true" tab="数据中心" key="2">
                <div class="chartbox">
                  <ve-histogram :data="countLocation" :judge-width="true" :extend="chartExtend" height="220px"></ve-histogram>
                </div>
              </a-tab-pane>
            </a-tabs>
          </div>
        </a-card>
      </a-col>  
    </a-row>

    <a-row :gutter="24">
      <a-col :xl="24" :lg="24" :md="8" :sm="24" :style="{marginBottom: '10px'}">
        <a-card title="最近十条严重告警事件" :bordered="false" :headStyle="{ padding: '0 15px', border:0, marginTop: '5px'}" style="width:100%">
          <a-spin :spinning="loading">
            <a-table
              row-key="serial"
              size="default"
              :columns="alarmListColumns"
              :dataSource="alarmListData"
              :pagination="{ pageSize: 5 }"
            >
            </a-table>
          </a-spin>
        </a-card>
      </a-col>
    </a-row>
  </div>
</template>

<script>
import moment from 'moment'
import { executeBySqlCmd } from '@/api/objectserver'
import roseTypeChart from './component/roseTypeChart'
import {
  ChartCard,
  MiniArea,
  MiniBar,
  MiniProgress,
  Bar,
  Trend,
  NumberInfo,
  STable,
  Ellipsis,
  MiniSmoothArea
} from '@/components'
import { baseMixin } from '@/store/app-mixin'

export default {
  name: 'Analysis',
  mixins: [baseMixin],
  components: {
    ChartCard,
    MiniArea,
    MiniBar,
    MiniProgress,
    Bar,
    Trend,
    NumberInfo,
    MiniSmoothArea,
    roseTypeChart,
    STable,
    Ellipsis
  },
  data () {
    return {
      loading: true,

      count_sev: [],
      count_app: [],
      count_loc: [],

      // Rose(玫瑰饼图)
      optionRoseType: {
        tooltip: {
          trigger: 'item',
          formatter: '{a} <br/>{b} : {c} ({d}%)'
        },
        legend: {
          top: 'bottom'
        },
        series: [
          {
            name: '级别分布',
            type: 'pie',
            radius: [25, 80],
            center: ['45%', '40%'],
            roseType: 'area',
            itemStyle: {
                borderRadius: 8
            },
            data: []
          }
        ]
      },

      // 柱状图
      chartExtend: {
        legend: {
          show: true,
          top: '0'
        },
        dataZoom: [
          {
            type: 'inside'
          }
        ],
        grid: {
          top: '15%',
          left: '1%',
          right: '3%',
          bottom: '5%',
          containLabel: true
        },
        color: ['#4ad2ff', '#00b436', '#fdcc74', '#4f91f1'],
        tooltip: {
          trigger: 'axis',
          axisPointer: {
            type: 'shadow',
            crossStyle: {
              color: '#999'
            }
          }
        }
      },

      countAppName: {
        columns: ['类型', '告警数量分布'],
        rows: []
      },

      countLocation: {
        columns: ['类型', '告警数量分布'],
        rows: []
      },

      alarmListColumns: [
        {
          title: '内部编号',
          dataIndex: 'serial',
          scopedSlots: { customRender: 'serial' },
          width: 100
        }, {
          title: '设备名称',
          dataIndex: 'node',
          scopedSlots: { customRender: 'node' },
          width: 200
        }, {
          title: '设备地址',
          dataIndex: 'node_alias',
          width: 150
        }, {
          title: '告警内容',
          dataIndex: 'summary',
          scopedSlots: { customRender: 'summary' },
          width: 400
        }, {
          title: '告警次数',
          dataIndex: 'tally',
          width: 100
        }, {
          title: '首次发生时间',
          dataIndex: 'first_occurrence',
          width: 200
        }, {
          title: '最近发生时间',
          dataIndex: 'last_occurrence',
          width: 200
        }, {
          title: '业务应用',
          dataIndex: 'app_name',
          width: 150
        }, {
          title: '机房位置',
          dataIndex: 'location',
          width: 100
        }, {
          title: '工单编号',
          dataIndex: 'bmc_identifier',
          width: 200,
          scopedSlots: { customRender: 'worksheet' }
        }
      ],

      alarmListData: []
    }
  },

  created () {
    setTimeout(() => {
      this.loading = !this.loading
    }, 1000)
  },

  mounted () {
    // 测试用: 模拟静态数据
    // this.getAlertsCountBySeverity()
    // this.getAlertsCountByAppName()
    // this.getEventList()

    // 生产用: 发起API请求
    this.getCountBySeverity()
    this.getCountByAppName()
    this.getCountByLocation()
    this.getTop10Events()
  },

  methods: {
    // 请求数据
    async getCountBySeverity () {
      this.count_sev = await this.getSeverity()
      const _this = this // 否则foreach内提示异常

      this.count_sev.forEach(function (item) {
        // console.log(item.agg_key)
        // console.log(item.agg_value)

        var _name, _color
        if (item.agg_key === 0) {
          _name = '清除'
          _color = '#93cb79'
        } else if (item.agg_key === 2) {
           _name = '警告'
          _color = '#76c0dc'
        } else if (item.agg_key === 3) {
           _name = '主要'
          _color = '#f5a337'
        } else if (item.agg_key === 5) {
          _name = '严重'
          _color = '#ec6769'
        }

        _this.optionRoseType.series[0].data.push(
          {
            value: item.agg_value, 
            name: _name,
            itemStyle: {
              normal: {
                color: _color
              }
            }
          }  
        )
      })
    },

    getSeverity () {
      const params = {
        sqlcmd: 'select count(*) as agg_value, Severity as agg_key from alerts.status where Severity in (0,2,3,5) group by agg_key'
      }
      return new Promise((resolve, reject) => {
        executeBySqlCmd(params).then(
          (res) => {
            resolve(res)
          },
          (error) => {
            console.log(error)
            resolve(error)
          }
        )
      })
    },

    async getCountByAppName () {
      this.count_app = await this.getAppName()
      const _this = this // 否则foreach内提示异常
      
      this.count_app.forEach(function (item) {
        // console.log(item.agg_key)
        // console.log(item.agg_value)

        _this.countAppName.rows.push(
          {
            '类型': item.agg_key,
            '告警数量分布': item.agg_value
          }
        )
      })
    },

    getAppName () {
      const params = {
        sqlcmd: `select count(*) as agg_value, app_name as agg_key from alerts.status where app_name != '' group by agg_key`
      }
      return new Promise((resolve, reject) => {
        executeBySqlCmd(params).then(
          (res) => {
            resolve(res)
          },
          (error) => {
            console.log(error)
            resolve(error)
          }
        )
      })
    },

    async getCountByLocation () {
      this.count_loc = await this.getLocation()
      const _this = this // 否则foreach内提示异常
      
      this.count_loc.forEach(function (item) {
        // console.log(item.agg_key)
        // console.log(item.agg_value)

        _this.countLocation.rows.push(
          {
            '类型': item.agg_key,
            '告警数量分布': item.agg_value
          }
        )
      })
    },

    getLocation () {
      const params = {
        sqlcmd: `select count(*) as agg_value, Location as agg_key from alerts.status where Location != '' group by agg_key`
      }
      return new Promise((resolve, reject) => {
        executeBySqlCmd(params).then(
          (res) => {
            resolve(res)
          },
          (error) => {
            console.log(error)
            resolve(error)
          }
        )
      })
    },

    async getTop10Events () {
      this.events = await this.getEventsBySql()
      const _this = this // 否则foreach内提示异常
      
      this.events.forEach(function (item) {
        var firstTime = new Date(item.FirstOccurrence * 1000)
        var lastTime = new Date(item.LastOccurrence * 1000)

        _this.alarmListData.push({
          serial: item.Serial, 
          node: item.Node, 
          node_alias: item.NodeAlias,
          summary: item.Summary,
          tally: item.Tally,
          first_occurrence: firstTime.toLocaleString(),
          last_occurrence: lastTime.toLocaleString(),
          app_name: item.app_name,
          location: item.Location,
          bmc_identifier: item.bmc_identifier
        })
      })
    },

    getEventsBySql () {
      const params = {
        sqlcmd: `select top 10 
        Serial, Node, NodeAlias, Summary, Tally, FirstOccurrence, LastOccurrence, app_name, Location, bmc_identifier 
        from alerts.status 
        where Severity = 5 order by LastOccurrence desc`
      }
      return new Promise((resolve, reject) => {
        executeBySqlCmd(params).then(
          (res) => {
            resolve(res)
          },
          (error) => {
            console.log(error)
            resolve(error)
          }
        )
      })
    },

    /*
     * 测试数据:
     * 告警事件列表
     */
    getEventList () {
      for (let i = 0; i < 5; i += 1) {
        this.alarmListData.push({
          node: 'S5720-BMC-101', 
          node_alias: '10.20.240.4',
          summary: 'Network interface link down',
          tally: '1',
          fisrt_occurrence: '2021-03-10 12:20:33',
          last_occurrence: '2021-04-08 17:20:33',
          app_name: '视频云',
          location: '事务局',
          incident_number: '100000001'
        })
      }
    },

    /*
     * 测试数据:
     * 告警事件数量根据严重级别进行统计
     */
    getAlertsCountBySeverity () {
      this.optionRoseType.series[0].data = [
        {
          value: 10, 
          name: '严重',
          itemStyle: {
            normal: {
              color: '#ec6769'
            }
          }
        },
        {
          value: 10, 
          name: '主要',
          itemStyle: {
            normal: {
              color: '#f5a337'
            }
          }
        },
        {
          value: 30, 
          name: '警告',
          itemStyle: {
            normal: {
              color: '#76c0dc'
            }
          }
        },
        {
          value: 20, 
          name: '清除',
          itemStyle: {
            normal: {
              color: '#93cb79'
            }
          }
        }
      ]
    },

    /**
     * 测试数据:
     * 严重告警事件数量根据业务应用进行统计
     */
    getAlertsCountByAppName () {
      this.countAppName.rows.push(
        {
          '类型': '日志审计', 
          '严重告警数量分布': 100
        },
        {
          '类型': '智能运维', 
          '严重告警数量分布': 200
        },
        {
          '类型': '指挥调度', 
          '严重告警数量分布': 300
        },
        {
          '类型': '六标一识', 
          '严重告警数量分布': 200
        },
        {
          '类型': '安全认证', 
          '严重告警数量分布': 400
        }
      )
    },

    /**
     * 告警类型信息汇总
     */
    getAlarmTypeData () {
      // 生产当月的开始日期
      const startDate = new Date(moment(new Date()).format('YYYY-MM-DD 00:00:00')).getTime()
      const endDate = new Date(moment(new Date()).format('YYYY-MM-DD 23:59:59')).getTime()
      for (let i = 0; i < 5; i += 1) {
        this.alarmTypeData.rows.push({
          '日期': moment(this.randomDate(startDate, endDate)).format('YYYY-MM-DD HH:mm:ss'),
          '紧急告警': Math.floor(Math.random() * 10), // 输出0～10之间的随机数
          '主要告警': Math.floor(Math.random() * 100), // 输出0～100之间的随机数
          '次要告警': Math.floor(Math.random() * 100), // 输出0～100之间的随机数
          '警告告警': Math.floor(Math.random() * 100) // 输出0～100之间的随机数
        })
      }
      this.alarmTypeData.rows.sort(function (a, b) {
        return Date.parse(a[ '日期' ]) - Date.parse(b[ '日期' ]) // 时间正序
      })
    },

    /***
     * 告警列表详情
     */
    getAlarmListDetails () {
      // 生产当天的开始日期
      const startDate = new Date(moment(new Date()).format('YYYY-MM-DD 00:00:00')).getTime()
      const endDate = new Date(moment(new Date()).format('YYYY-MM-DD 23:59:59')).getTime()
      for (let i = 0; i < 20; i += 1) {
        this.alarmListData.push({
          name: `spark_alarm ${i}`,
          host: `am2x0 ${i}`,
          ip: `10.11.21.${i}`,
          details: (i % 2 === 0) ? '监控数据告警' : '事件告警',
          alarmTime: moment(this.randomDate(startDate, endDate)).format('YYYY-MM-DD HH:mm:ss'),
          status: Math.floor(Math.random() * 3 + 1) // 随机生成1-3的数字       
        })
        this.loading = false
      }
      this.alarmListData.sort(function (a, b) {
        return Date.parse(a[ 'alarmTime' ]) - Date.parse(b[ 'alarmTime' ]) // 时间正序
      })
      this.alarmListData.forEach((item) => {
        item['alarmTime'] = moment(item['alarmTime']).format('HH:mm:ss')
      })
    },

    /**
     * 生成指定时间段的随机时间
     */
    randomDate (startDate, endDate) {
      const date = new Date(+startDate + Math.random() * (endDate - startDate))
      const hour = 0 + Math.random() * (23 - 0) | 0
      const minute = 0 + Math.random() * (59 - 0) | 0
      const second = 0 + Math.random() * (59 - 0) | 0
      date.setHours(hour)
      date.setMinutes(minute)
      date.setSeconds(second)
      return date
    }
  }
}
</script>

<style lang="less" scoped>
  /deep/.cardpadding{
    .ant-card-body{
      padding: 0!important;
    }
  }
  .chartbox{
    padding: 10px;
  }
  .extra-wrapper {
    line-height: 55px;
    padding-right: 24px;

    .extra-item {
      display: inline-block;
      margin-right: 24px;

      a {
        margin-left: 24px;
      }
    }
  }

  .antd-pro-pages-dashboard-analysis-twoColLayout {
    position: relative;
    display: flex;
    display: block;
    flex-flow: row wrap;
  }

  .antd-pro-pages-dashboard-analysis-salesCard {
    height: calc(100% - 24px);
    /deep/ .ant-card-head {
      position: relative;
    }
  }

  .dashboard-analysis-iconGroup {
    i {
      margin-left: 16px;
      color: rgba(0,0,0,.45);
      cursor: pointer;
      transition: color .32s;
      color: black;
    }
  }
  .analysis-salesTypeRadio {
    position: absolute;
    right: 54px;
    bottom: 12px;
  }
</style>
